package com.ody.util.code.model;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.odianyun.project.util.function.TriConsumer;
import java.util.List;
import java.util.Set;
import java.util.function.BiConsumer;

public abstract class POModelProvider extends AbstractModelProvider implements IModelProvider {
	
	@Override
	public List<Model> provide() {
		List<POBean> list = getPOList();
        for (POBean po : list) {
            List<FieldBean> searchFields = Lists.newArrayList();
            List<FieldBean> tableFields = Lists.newArrayList();
            List<FieldBean> editFields = Lists.newArrayList();
            List<FieldBean> importFields = Lists.newArrayList();
            List<FieldBean> exportFields = Lists.newArrayList();
            po.setSearchFields(searchFields);
            po.setTableFields(tableFields);
            po.setEditFields(editFields);
            po.setImportFields(importFields);
            po.setExportFields(exportFields);
    
            Set<String> checkNameRepeat = Sets.newHashSet();
            
            TriConsumer<FieldBean, Boolean, Boolean> consumer = (field, isMain, isMulti) -> {
                searchFields.add(field.clone());
                if (isMain || !isMulti) {
                    // 列表字段可以放主表和一对一的字段
                    tableFields.add(field.clone());
                    if (!field.isCommon()) {
                        // 编辑表单可以放主表和一对一的非公共字段
                        editFields.add(field.clone());
                    }
                }
                if (!field.isCommon()) {
                    importFields.add(field.clone());
                }
                exportFields.add(field.clone());
            };
    
            BiConsumer<FieldBean, String> fieldConsumer = (field, prefix) -> {
                if (prefix != null) {
                    if (po.getFields().stream().anyMatch(f -> f.getName().equals(field.getName()))
                            || checkNameRepeat.contains(field.getName())) {
                        field.setRelName(prefix + field.getCapName());
                    }
                    checkNameRepeat.add(field.getName());
                }
            };
    
            fillFields(po, null, true, false, consumer, fieldConsumer);
    
            if (po.getRelOneList() != null) {
                for (RelPOBean rel : po.getRelOneList()) {
                    fillFields(rel, rel.getUncapName(), false, false, consumer, fieldConsumer);
                }
            }
            if (po.getRelManyList() != null) {
                for (RelPOBean rel : po.getRelManyList()) {
                    fillFields(rel, rel.getUncapName(), false, true, consumer, fieldConsumer);
                }
            }
        }
		List<Model> result = Lists.newArrayList(new Model("po", list, true));
		
		if (getModelList() != null) result.addAll(getModelList());
		
		return result;
	}
	
	private void fillFields(POBean po, String prefix, boolean isMain, boolean isMulti,
                            TriConsumer<FieldBean, Boolean, Boolean> consumer,
                            BiConsumer<FieldBean, String> fieldConsumer) {
        for (FieldBean field : po.getNonCommonFields()) {
            fieldConsumer.accept(field, prefix);
            consumer.accept(field, isMain, isMulti);
        }
    }

	protected abstract List<POBean> getPOList();
}
